namespace GYLite
{
    interface IKeyObject
    {
        value:any;
        index:number;
    }
    /**key数组，是一种无序数组，需要指定一个唯一key并且相同key的对象加入到数组会覆盖原来的key的value，此数组无序，无法保证数组内的元素顺序，可通过指定的唯一key访问数组元素，也可以通过下标访问*/
    export class KeyArray
    {
        public list:any[];
        public dict:{[key:string]:IKeyObject};
        private _key:string;
        /**数组元素指定的唯一key*/
        constructor(key:string)
        {
            if(key == null)
            {
                throw(new Error("必须指定合法的key"));
            }
            this.list = [];
            this.dict = {};
            this._key = key;
        }        
        public push(...items):number
        {
            let s= this;
            let i:number,len:number;            
            len = items.length;
            for(i=0;i<len;++i)                     
                s.setByIndex(s.list.length, items[i]);
            return s.list.length;
        }
        /**注意,由于此对象是无序列表，所以第三个参数items只会在末尾添加元素，而并不从删除的位置插入*/
        public splice(start:number,deleteCount:number, ...items:any[]):any[]
        {
            let i:number,len:number;            
            let s= this;
            let list:any[] = [];
            len = deleteCount;
            if(len > 0)
            {
                len = start + deleteCount;
                for(i=start;i<len;++i)            
                    list.push(s.list[i]);
                len = list.length;
                while(--len>-1)            
                    s.removeObject(list[len]);
            }            
            s.push(...items);
            return list;
        }
        public sort(func:(a,b)=>number):void
        {
            let s= this;
            let len:number;
            let key:string|number;
            s.list.sort(func);
            len = s.list.length;
            while(--len>-1)
            {
                key = s.list[len][s._key];
                s.dict[key].index = len;
            }
        }
        public pop():any
        {
            return this.remove(this.list.length - 1);
        }
        public shift():any
        {            
            return this.remove(0);
        }
        /**移除指定对象*/
        public removeObject(obj:any):void
        {
            let s= this;            
            let key:string;    
            if(obj == null)return;
            key = obj[s._key];
            if(s.dict[key] == null)return;
            s.remove(s.dict[key].index);            
        }
        /**移除指定索引上的对象
         * (注意，每次移除对象，会获取列表最后一个对象，填充到移除的索引位置上，以便保证其他对象索引不变，但是最后一个对象的会被改变，所以请勿循环移除索引对象，因为此列表本身是无序的)
         * 
        */
        public remove(index:number):any
        {
            let s= this;
            let obj:any;            
            let key:string;            
            if(index >= s.list.length)return null;
            if(index < 0)return null;
            obj = s.list[index];           
            s.list[index] = s.list[s.list.length - 1];
            key = s.list[index][s._key];
            s.dict[key].index = index;
            s.list.length = s.list.length - 1;
            delete s.dict[obj[s._key]];
            return obj;
        }
        public unshift(...items: any[]):number
        {
            let s= this;
            let len:number;            
            len = items.length;
            while(--len>-1)                     
                s.setByIndex(0,items[len]);
            return s.list.length;
        }
        /**根据key交换数组内两个对象的位置**/
        public swapByKey(keyA:string|number, keyB:string|number):void
        {
            let s= this;            
            let keyObjA:IKeyObject,keyObjB:IKeyObject;
            keyObjA = s.dict[keyA];
            keyObjB = s.dict[keyB];
            s.list[keyObjA.index] = keyObjB.value;
            s.list[keyObjB.index] = keyObjA.value;
            s.dict[keyA].index = keyObjB.index;
            s.dict[keyB].index = keyObjA.index;
        }
        /**交换数组内两个对象的位置**/
        public swap(objA:any, objB:any):void
        {
            let s= this;            
            s.swapByKey(objA[s._key],objB[s._key]);
        }
        /**是否存在指定key的对象*/
        public hasKey(key:string|number):boolean
        {
            return !!this.dict[key];
        }
        /**设置指定key上的对象*/
        public setByKey(key:string|number,value:any):void
        {
            let s= this;
            let keyObj:IKeyObject;
            if(s.dict[key] == null)       
            {
                s.push(key, value);
                return;
            }
                
            keyObj = s.dict[key];            
            keyObj.value = value;
        }
        /**根据key删除对象*/
        public deleteByKey(key:string):void
        {
            this.removeObject(this.dict[key]);
        }
        /**获取指定key上的对象*/
        public getByKey(key:string|number):any
        {
            return this.dict[key]?this.dict[key].value:null;
        }
        /**设置指定索引上的对象*/
        public setByIndex(index:number, value:any):void
        {
            let keyObj:any;
            let key:string;
            let s= this;
            if(index < 0 || index > s.list.length)return;
            key = value[s._key];
            if(s.dict[key] == null)       
                s.dict[key] = {index:index,value:value}
            else
            {
                keyObj = s.dict[key];
                keyObj.index = index;
                keyObj.value = value;
            }            
            s.list[index] = value;
        }
        public set length(val:number)
        {
            let i:number,len:number;
            let s= this;
            let list:any[];
            if(val == 0)
            {
                s.dict = {};
                s.list.length = 0;
                return;
            }
            list = [];
            len = s.list.length;
            for(i=val;i<len;++i)            
                list.push(s.list[i]);
            len = list.length;
            for(i=0;i<len;++i)     
                s.removeObject(list[i]);
        }
        public get length():number
        {
            return this.list.length;
        }
    }
}